﻿using System;
using System.Collections.Generic;
using LoungeRepo.Contracts.Core;
using LoungeRepo.Contracts.Normalizer;
using LoungeRepo.Normalizer.DataStructures;


namespace LoungeRepo.Normalizer
{
    internal partial class ObjectGraphNormalizer
    {
        private readonly Dictionary<object, INormalizedObjectReference> normalizedObjectCache = new Dictionary<object, INormalizedObjectReference>();
        private readonly IList<INormalizedEntity> normalizedEntities = new List<INormalizedEntity>();


        public IEnumerable<INormalizedEntity> NormalizeEntityGraph(object entityObject, ILoungeRepoEntityIdentity entityIdentity)
        {
            NormalizeEntity(entityObject, entityIdentity);
            return this.normalizedEntities;
        }


        public bool TryExtractEntityIdentity(object entityObject, out ILoungeRepoEntityIdentity entityIdentity)
        {
            entityIdentity = entityObject as ILoungeRepoEntityIdentity;
            return entityIdentity != null;

            //TODO: check for entities not implementing ILoungeRepoEntityIdentity
        }


        internal NormalizedEntityReference NormalizeEntity(object entityObject, ILoungeRepoEntityIdentity entityIdentity)
        {
            NormalizedEntity normalizedEntity = CreateNormalizedEntityToBeFilled(entityObject, entityIdentity);
            NormalizedEntityReference normalizedEntityRef = CreateReferenceToNormalizedEntity(entityObject, entityIdentity);

            TransferObjectIntoNormalizedObject(entityObject, normalizedEntity);

            return normalizedEntityRef;
        }


        internal NormalizedObject NormalizeNonEntity(object nonEntity)
        {
            NormalizedObject normalizedObject = CreateNormalizedObjectToBeFilled(nonEntity);

            TransferObjectIntoNormalizedObject(nonEntity, normalizedObject);

            return normalizedObject;
        }


        internal NormalizedObject NormalizeArray(Array array)
        {
            var normalizedArray = CreateNormalizedObjectToBeFilled(array);

            normalizedArray.AddField("_arrayRank", array.Rank);
            for (int dimension = 0; dimension < array.Rank; dimension++)
                normalizedArray.AddField("_dimLength", array.GetLength(dimension));

            int i = 0;
            foreach(object element in array)
            {
                normalizedArray.AddField(i.ToString(), NormalizeFieldValue(element));
                i++;
            }

            return normalizedArray;
        }
    }
}
